package demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import jdk.nashorn.internal.objects.annotations.Getter;

/**
 * @program: mccken-collect
 * @description:
 * @author: mccken
 * @create: 2021-10-08 19:59
 **/
public class SelectorDemo {
	
	private Selector getSelector() throws Exception {

		// 获取Selector对象
		Selector selector = Selector.open();

		// 获取SelectChannel
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); 
		serverSocketChannel.configureBlocking(false);  // 设置非阻塞
		
		// 获取通道并绑定端口
		ServerSocket socket = serverSocketChannel.socket();
		socket.bind(new InetSocketAddress(6677));
		
		// 注册感兴趣的事件
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		return selector;
	}
	
	public void listen() throws Exception {
		Selector selector = this.getSelector();
		
		while (true) {
			// 该方法会阻塞，知道至少有一个事件的发生
			selector.select();

			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			Iterator<SelectionKey> iterator = selectionKeys.iterator();
			
			while (iterator.hasNext()) {
				SelectionKey selectionKey = iterator.next();
				process(selectionKey, selector);
				iterator.remove();
			}
		}
	}

	private void process(SelectionKey selectionKey, Selector selector) throws Exception {
		// 新连接请求
		if (selectionKey.isAcceptable()) {
			ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();
			SocketChannel channel = server.accept();
			channel.configureBlocking(false);
			// 注册读事件
			channel.register(selector, SelectionKey.OP_READ);
		} else if (selectionKey.isReadable()) {
			// 是读事件，处理：
			
			SocketChannel channel = (SocketChannel) selectionKey.channel();
			ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
			channel.read(byteBuffer);

			System.out.println("from 客户端 " + new String(byteBuffer.array(), 0, byteBuffer.position()));
		}
	}

	public static void main(String[] args) throws Exception {
		new SelectorDemo().listen();
	}

}
